/*jslint maxlen:150*/
/*global define:false, K:false*/
define( 'core/panel/AsyncDialog', [ 'jQuery', 'core/async/Request', 'core/panel/Dialog' ], function( require ) {

    var $ = require( 'jQuery' ),
        Request = require( 'core/async/Request' ),
        Dialog = require( 'core/panel/Dialog' );

    var AsyncDialog = function( opts ) {
        //实例消息
        this.pb = new K.Pubsub();
        AsyncDialog.$super.call( this, opts );
    };

    K.extend( AsyncDialog, Dialog );

    K.mix( AsyncDialog, {
        instances: {},

        generateID: function( ) {
            return K.uniqueId( '__dialog__' );
        },

        getInstance: function( dialogId ) {
            return AsyncDialog.instances[ dialogId ];
        },

        destroy: function( dialogId ) {
            if ( dialogId in AsyncDialog.instances ) {
                delete AsyncDialog.instances[ dialogId ];
                // TODO stackable
            }
        },
        /**
		 * 异步加载Dialog数据（内容、资源）
		 * @static
		 * @param {String} href 异步请求URL
		 * @param {jQuery|HTMLElement|Object} 配置项
				1. 如果是元素，则从自定义属性读取配置项
				2. 也可以通过配置Object
					method: get / post ( 默认为get )
					loadingWidth: 加载时窗口宽度
					loadingHeight: 加载时窗口高度
					loadingContent: 加载时窗口内容
					autoShow: 自动显示窗口(默认为true)
           @param {Object} opts Dialog配置项
		 */
        load: function( href, element, opts ) {
            if ( !href ) {
                return;
            }

            var method = 'GET',
                data = {},
                loadingWidth = 350,
                loadingHeight = 100,
                loadingContent = AsyncDialog.loadingContent,
                autoShow = ( opts && ( 'autoShow' in opts ) ) ? opts.autoShow: true;

            if ( element ) {
                if ( $.isPlainObject( element ) ) {
                    method = element.method || method;
                    loadingWidth = element.loadingWidth || loadingWidth;
                    loadingHeight = element.loadingHeight || loadingHeight;
                    loadingContent = element.loadingContent || loadingContent;
                    data = element.data || data;
                }
                else {
                    var el = $( element );

                    method = el.attr( 'data-ajax' ) == 'dialog-post' ? 'POST' : method;
                    loadingWidth = el.attr( 'data-loading-width' ) || loadingWidth;
                    loadingHeight = el.attr( 'data-loading-height' ) || loadingHeight;
                    loadingContent = el.attr( 'data-loading-content' ) || loadingContent;

                    if( el.attr( 'data-data' ) ) {
                        data = $.parseJSON( el.attr( 'data-data' ) );
                    }
                }
            }

            var request = new Request( ).setMethod( method ).setData( data ).setURI( href );

            var dialog = new AsyncDialog( K.mix( {
                        content: loadingContent
                    }, opts ) )
                    .setAsyncRequest( request )
                    .setSize( loadingWidth, loadingHeight );

            if( autoShow ) {
                dialog.show();
            }

            return dialog;
        },

        loadingContent: 
            '<div style="top:35px;width:53px;position:relative;margin:0 auto;">' + 
                '<img src="http://' + K.Env.IMG_HOST + '/i/home/dt_loading_nobg.gif">' + 
            '</div>',

        handlerFactory: function( HandlerBase, id, metaData ) {
            var handler = K.create( HandlerBase );
            K.mix( handler, {
                container: 'div[data-dialog-id="' + id + '"]',
                metaData: metaData,
                getDialog: function( ) {
                    return AsyncDialog.getInstance( id );
                }
            } );
            return handler;
        }
    } );

    K.mix( AsyncDialog.prototype, {
        destroy: function( ) {
            this.dispose( );
            AsyncDialog.destroy( this._dialogId );
        },
        setAsyncRequest: function( request ) {
            var handler = function( response ) { 
                    /*请求不匹配或者窗口在loading时已被关闭则不再显示*/
                    if ( this._async_request != request || ( this.autoShow !== false && !this.visible ) ) {
                        return;
                    }
                    this._async_request = null;

                    var data = response.content.dialog,
                        dialogId = this._dialogId;

                    if ( !dialogId ) {
                        dialogId = this._dialogId = AsyncDialog.generateID( );
                        AsyncDialog.instances[ this._dialogId ] = this;
                    }

                    if ( data.title ) {
                        this.setTitle( data.title );
                    }
                    if ( data.body ) {
                        if ( !this.getPanel( ).find( 'div[data-dialog-id]' ).length ) {
                            this.setContent( '<div data-dialog-id="' + dialogId + '">' + data.body + '</div>' );
                        }
                        else {
                            this.getPanel( ).find( 'div[data-dialog-id]' ).html( data.body );
                        }
                    }
                    if ( data.width ) {
                        // TODO height 可以置成auto
                        this.setSize( data.width, data.height );
                    }

                    if( this.autoShow !== false ) {
                        this.show( );
                    }

                    if ( data.handler ) {
                        K.App( [ 'core/panel/AsyncDialog', data.handler ] ).define( function( require ) {
                            return require( 'core/panel/AsyncDialog' )
                                    .handlerFactory( require( data.handler ), dialogId, data.metaData );
                        } );
                    }
                };
            this._async_request = request;
            request.setHandler( K.bind( handler, this ) );
            request.send( );

            return this;
        }
    } );

    return AsyncDialog;
} );
